

<template>
  <div class="ProModal">

    <a-modal
        v-if="!isDrawer"
        ref="modalRef"
        :maskClosable="false"
        :visible="props.modelValue"
        :wrap-style="{ overflow: 'hidden' }"
        :width="650"
        @cancel="handle_cancel"
        @ok="handleOk"
    >
      <slot></slot>
      <template #title>
        <div ref="modalTitleRef" class="w-full cursor-move">{{ props.title }}</div>
      </template>
      <template #modalRender="{ originVNode }">
        <div :style="transformStyle">
          <component :is="originVNode" />
        </div>
      </template>

      <template #footer>
        <slot name="footer"></slot>
      </template>
    </a-modal>

    <a-drawer
        v-else
        :visible="props.modelValue"
        :maskClosable="false"
        size="large"
        placement="right"
        @close="handle_cancel"
    >
      <slot></slot>
      <template #title>
        {{ props.title }}
      </template>
      <template #footer>
        <slot name="footer"></slot>
      </template>
    </a-drawer>

  </div>
</template>

<script setup lang="ts">
import { ref, computed, CSSProperties, watch, watchEffect } from 'vue';
import { useDraggable } from '@vueuse/core';
const modalTitleRef = ref<HTMLElement>(null);

interface PropsType {
  modelValue:boolean;
  title:string;
  isDrawer?:boolean
}

// 接受父组件参数，配置默认值
const props = withDefaults(defineProps<PropsType>(), {
  modelValue:false,
  title:'',
  isDrawer:false
});


const { x, y, isDragging } = useDraggable(modalTitleRef);
const handleOk = (e: MouseEvent) => {
  console.log(e);
};
const startX = ref<number>(0);
const startY = ref<number>(0);
const startedDrag = ref(false);
const transformX = ref(0);
const transformY = ref(0);
const preTransformX = ref(0);
const preTransformY = ref(0);
const dragRect = ref({ left: 0, right: 0, top: 0, bottom: 0 });
watch([x, y], () => {
  if (!startedDrag.value) {
    startX.value = x.value;
    startY.value = y.value;
    const bodyRect = document.body.getBoundingClientRect();
    const titleRect = modalTitleRef.value.getBoundingClientRect();
    dragRect.value.right = bodyRect.width - titleRect.width;
    dragRect.value.bottom = bodyRect.height - titleRect.height;
    preTransformX.value = transformX.value;
    preTransformY.value = transformY.value;
  }
  startedDrag.value = true;
});
watch(isDragging, () => {
  if (!isDragging) {
    startedDrag.value = false;
  }
});

watchEffect(() => {
  if (startedDrag.value) {
    transformX.value =
        preTransformX.value +
        Math.min(Math.max(dragRect.value.left, x.value), dragRect.value.right) -
        startX.value;
    transformY.value =
        preTransformY.value +
        Math.min(Math.max(dragRect.value.top, y.value), dragRect.value.bottom) -
        startY.value;
  }
});
const transformStyle = computed<CSSProperties>(() => {
  return {
    transform: `translate(${transformX.value}px, ${transformY.value}px)`,
  };
});

// 父组件抛出方法
interface defineEmitType {
  (e: "update:modelValue",visible:boolean): void;
  (e: "close"): void;
}
const emit = defineEmits<defineEmitType>();

const handle_cancel = ()=>{
  emit("update:modelValue",false)
  emit("close");
}



</script>

<style scoped lang="less">

</style>
